package com.totem.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.totem.admin.mapper.TFundDailyEndMapper;
import com.totem.admin.model.TFundDailyEnd;
import com.totem.admin.vo.FundBalanceVO;
import com.totem.base.constants.CommonConstants;
import com.totem.base.enums.*;
import com.totem.order.mapper.TFundOrderItemMapper;
import com.totem.order.mapper.TOrderMapper;
import com.totem.order.mapper.TWalletJournalMapper;
import com.totem.order.model.TWalletJournal;
import com.totem.order.service.IOrderCommonService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OrderCommonServiceImpl implements IOrderCommonService {
    @Autowired
    private TOrderMapper tOrderMapper;
    @Autowired
    private TFundOrderItemMapper tFundOrderItemMapper;
    @Autowired
    private TWalletJournalMapper tWalletJournalMapper;
    @Autowired
    private TFundDailyEndMapper tFundDailyEndMapper;

    @Override
    public Map<Long, FundBalanceVO> queryFundBalance(List<Long> customerIdList) {
        LocalDate today = LocalDate.now();
        LocalDate yesterday = today.minusDays(1);
        LocalDateTime todayMidnight = today.atStartOfDay();
        Date todayMidnightDate = Date.from(todayMidnight.atZone(ZoneId.systemDefault()).toInstant());
        String yesterdayStr = CommonConstants.DEFAULT_DATE_FORMATTER.format(yesterday);

        LambdaQueryWrapper<TWalletJournal> journalQuery = new LambdaQueryWrapper<>();
        journalQuery.in(TWalletJournal::getCustomerId, customerIdList);
        journalQuery.eq(TWalletJournal::getJournalState, JournalStateEnum.FINISHED.getCode());
        journalQuery.in(TWalletJournal::getJournalType,
                JournalTypeEnum.FUND_RETURN.getCode(),
                JournalTypeEnum.FUND_ORDER.getCode(),
                JournalTypeEnum.FUND_WITHDRAW.getCode());
        journalQuery.ge(TWalletJournal::getCreateTime, todayMidnightDate);
        List<TWalletJournal> journalList = tWalletJournalMapper.selectList(journalQuery);
        Map<Long, BigDecimal> custTodayInvestMap = new HashMap<>();
        if(!CollectionUtils.isEmpty(journalList)) {
            Map<Long, List<TWalletJournal>> journalMap = journalList.stream().collect(Collectors.groupingBy(TWalletJournal::getCustomerId));

            journalMap.forEach((customerId, custJournalList) -> custJournalList.forEach(journal-> {
                BigDecimal custTodayInvest = custTodayInvestMap.get(customerId);
                if(custTodayInvest==null){
                    custTodayInvestMap.put(customerId, BigDecimal.ZERO);
                    custTodayInvest = custTodayInvestMap.get(customerId);
                }
                BigDecimal amt = journal.getAmount();
                BigDecimal charge = journal.getCharges();
                if(charge==null){
                    charge = BigDecimal.ZERO;
                }
                // 对钱包CREDIT是减, DEBIT是增; 对基金池则相反
                if (DirectionEnum.CREDIT.getCode().equals(journal.getDirection())) {
                    custTodayInvest = custTodayInvest.add(amt).add(charge);
                } else {
                    custTodayInvest = custTodayInvest.subtract(amt).subtract(charge);
                }
                custTodayInvestMap.put(customerId, custTodayInvest);
            }));
        }

        LambdaQueryWrapper<TFundDailyEnd> latestQuery = new LambdaQueryWrapper<>();
        latestQuery.in(TFundDailyEnd::getCustomerId, customerIdList);
        latestQuery.eq(TFundDailyEnd::getCutOffDay, yesterdayStr);
        latestQuery.orderByDesc(TFundDailyEnd::getId);
        List<TFundDailyEnd> custFundDailyEndList = tFundDailyEndMapper.selectList(latestQuery);

        Map<Long, List<TFundDailyEnd>> custFundEndMap = custFundDailyEndList.stream().collect(Collectors.groupingBy(TFundDailyEnd::getCustomerId));
        Map<Long, FundBalanceVO> fundBalMap = new HashMap<>();
        customerIdList.stream().map(customerId->{
            BigDecimal todayInvest = custTodayInvestMap.get(customerId);
            if(todayInvest==null){
                todayInvest = BigDecimal.ZERO;
            }
            List<TFundDailyEnd> fundDailyEndList = custFundEndMap.get(customerId);
            FundBalanceVO fundBalVO = new FundBalanceVO();
            fundBalVO.setCustomerId(customerId);
            fundBalVO.setInvest(todayInvest);
            fundBalVO.setEarnings(BigDecimal.ZERO);
            fundBalVO.setAccEarnings(BigDecimal.ZERO);
            if(!CollectionUtils.isEmpty(fundDailyEndList)){
                Optional<TFundDailyEnd> latestOpt = fundDailyEndList.stream().max(Comparator.comparing(TFundDailyEnd::getId));
                TFundDailyEnd latest = latestOpt.get();
                BigDecimal latestInvest = latest.getInvest();
                BigDecimal latestEarnings = latest.getEarnings();
                BigDecimal latestAccEarnings = latest.getAccEarnings();

                fundBalVO.setInvest(fundBalVO.getInvest().add(latestInvest));
                fundBalVO.setEarnings(latestEarnings);
                fundBalVO.setAccEarnings(latestAccEarnings);
            }

            // 取相反值以便展示
            if(fundBalVO.getInvest()!=null){
                fundBalVO.setInvest(fundBalVO.getInvest());
            }
            fundBalMap.put(customerId, fundBalVO);
            return fundBalVO;
        }).toList();
        return fundBalMap;
    }
}
